package com.example.portablefortheelderlybackground.config.Security;

import com.example.portablefortheelderlybackground.Filter.JwtAuthenticationTokenFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity(debug = true)//开启debug模式
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public SecurityConfig(AuthenticationEntryPointImpl authenticationEntryPoint, JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter, AccessDeniedExceptionImpl accessDeniedException) {
        this.authenticationEntryPoint = authenticationEntryPoint;
        this.jwtAuthenticationTokenFilter = jwtAuthenticationTokenFilter;
        this.accessDeniedException = accessDeniedException;
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {//
        return new BCryptPasswordEncoder();
    }

    final
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    final
    AccessDeniedExceptionImpl accessDeniedException;
    final
    AuthenticationEntryPointImpl authenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //关闭csrf
                .csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //开启权限验证
                .authorizeRequests()
                // 对于登录接口 允许匿名访问
                .mvcMatchers(AllowedInterfaces.getAnonymousUrl()).anonymous().
                //mvcMatchers(AllowedInterfaces.getPermitUrl()).permitAll().
                // 除上面外的所有请求全部需要鉴权认证
                        anyRequest().authenticated();
        //注入自定义过滤器,在UsernamePasswordAuthenticationFilter之前
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        //注入自定义的异常handler,认证和权限异常handler
        http.exceptionHandling().accessDeniedHandler(accessDeniedException).authenticationEntryPoint(authenticationEntryPoint);
        http.cors();//开启跨域访问
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //配置忽略路径
        // 忽略options请求
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**").
                //对于公共页面,设置不需要登录即可访问,即不需要进行登录和鉴权
                        mvcMatchers(AllowedInterfaces.getPermitUrl());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}